package net.orange.architecture.db;

import java.util.Collection;
import java.util.Map;

import net.orange.architecture.model.BaseValueObject;

/**
 * The base cache data access object. when the system access the data, it will
 * search in the memory first. If it can't be found, so will continue search in
 * database. While updating the data, system will update the whole cache.
 */
public abstract class PositiveCacheDao implements ICacheDao {

	/**
	 * The delegate base DAO.
	 */
	private IObjectManager target;

	/**
	 * @return Returns the target.
	 */
	public IObjectManager getTarget() {
		return target;
	}

	/**
	 * @param target
	 *            The target to set.
	 */
	public void setTarget(IObjectManager target) {
		this.target = target;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.orange.architecture.db.IBaseDao#getValueObjectClassName()
	 */
	public String getValueObjectClassName() {
		return target.getValueObjectClassName();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * net.orange.architecture.db.IBaseDao#setValueObjectClassName(java.lang
	 * .String)
	 */
	public void setValueObjectClassName(String valueObjectClassName)
			throws Exception {
		target.setValueObjectClassName(valueObjectClassName);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.orange.architecture.db.IBaseDao#list(net.orange.architecture.db.
	 * Conditions)
	 */
	public Collection list(Conditions cds) throws Exception {
		Collection r = target.list(cds);
		return r;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.orange.architecture.db.IBaseDao#list(net.orange.architecture.db.
	 * Conditions, net.orange.architecture.db.Orders)
	 */
	public Collection list(Conditions cds, Orders orders) throws Exception {
		Collection r = target.list(cds, orders);
		return r;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * net.orange.architecture.db.IBaseDao#list2(net.orange.architecture.db.
	 * ListConditions)
	 */
	public Collection list2(ListConditions cds) throws Exception {
		Collection r = target.list2(cds);
		return r;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.orange.architecture.db.IBaseDao#list(java.lang.String)
	 */
	public Collection list(String s) throws Exception {
		Collection r = target.list(s);
		return r;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.orange.architecture.db.IBaseDao#find(long)
	 */
	public BaseValueObject find(long id) throws Exception {
		BaseValueObject r = target.find(id);
		return r;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.orange.architecture.db.IBaseDao#find(java.lang.String,
	 * java.lang.String)
	 */
	public BaseValueObject find(String field, String code) throws Exception {
		BaseValueObject r = target.find(field, code);
		return r;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.orange.architecture.db.IBaseDao#find(net.orange.architecture.db.
	 * Conditions)
	 */
	public BaseValueObject find(Conditions cds) throws Exception {
		BaseValueObject r = target.find(cds);
		return r;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * net.orange.architecture.db.IBaseDao#create(net.orange.architecture.vo
	 * .BaseValueObject)
	 */
	public boolean create(BaseValueObject b0) throws Exception {
		boolean r = target.create(b0);
		refreshCache();
		return r;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * net.orange.architecture.db.IBaseDao#update(net.orange.architecture.vo
	 * .BaseValueObject)
	 */
	public boolean update(BaseValueObject b0) throws Exception {
		boolean r = target.update(b0);
		refreshCache();
		return r;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * net.orange.architecture.db.IBaseDao#createOrUpdate(net.orange.architecture
	 * .vo.BaseValueObject)
	 */
	public boolean createOrUpdate(BaseValueObject b0) throws Exception {
		boolean r = target.createOrUpdate(b0);
		refreshCache();
		return r;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * net.orange.architecture.db.IBaseDao#delete(net.orange.architecture.vo
	 * .BaseValueObject)
	 */
	public boolean delete(BaseValueObject b0) throws Exception {
		boolean r = target.delete(b0);
		refreshCache();
		return r;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.orange.architecture.db.IBaseDao#delete(long)
	 */
	public boolean delete(long id) throws Exception {
		boolean r = target.delete(id);
		refreshCache();
		return r;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.orange.architecture.db.IBaseDao#batchUpdate(java.lang.String)
	 */
	public int batchUpdate(String s) throws Exception {
		int r = target.batchUpdate(s);
		refreshCache();
		return r;
	}

	/**
	 * Get the key of the value objct.
	 * 
	 * @param b0
	 *            The value object;
	 * @return The key of the value object.
	 * @throws Exception
	 */
	protected abstract Object getKey(BaseValueObject b0) throws Exception;

	/*
	 * (non-Javadoc)
	 * 
	 * @see net.orange.architecture.db.ICacheDao#findByKey(java.lang.Object)
	 */
	public Object findByKey(Object key) throws Exception {
		if (getCache() == null || getCache().size() <= 0)
			refreshCache();
		return (Object) getCache().get(key);
	}

	/**
	 * Refresh the cache.
	 * 
	 * @throws Exception
	 */
	protected void refreshCache() throws Exception {
		Collection list = list(new Conditions());

		getCache().clear();

		for (Object object : list)
			getCache().put(getKey((BaseValueObject) object), object);
	}

	/**
	 * @return Returns the cache.
	 */
	public abstract Map<Object, Object> getCache();

	/**
	 * @param cache
	 *            The cache to set.
	 */
	public abstract void setCache(Map<Object, Object> cache);
}
